package com.hexacta.hrs.test.data;

import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Map;

import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.math.RandomUtils;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.vectrics.common.util.DateUtil;
import org.vectrics.company.Company;
import org.vectrics.domain.Domain;
import org.vectrics.employee.Employee;
import org.vectrics.employee.EmployeeStatus;
import org.vectrics.location.Locale;
import org.vectrics.location.Location;
import org.vectrics.recruiter.job.JobTerm;
import org.vectrics.user.Person;

import com.hexacta.hrs.domain.employee.history.AgreementCondition;
import com.hexacta.hrs.domain.employee.history.CareerRole;
import com.hexacta.hrs.domain.employee.history.MentorAssignment;
import com.hexacta.hrs.domain.staffing.Client;
import com.hexacta.hrs.domain.staffing.Project;
import com.hexacta.hrs.domain.staffing.assignment.AssignmentType;
import com.hexacta.hrs.domain.staffing.assignment.EmployeeAssignment;
import com.hexacta.hrs.util.Cuit;

/**
 * Static utility methods for creating test data.
 * 
 * @author tpollak
 */
public class DataUtils {
    private SessionFactory sessionFactory;

    public String createAddressString() {
        return RandomStringUtils.randomAlphabetic(8);
    }

    public String createCode() {
        return RandomStringUtils.randomAlphabetic(4);
    }

    public Date createCurrentDate() {
        return DateUtil.getFechaHoraActual();
    }

    public Date createDateStart() {
        return new GregorianCalendar(2005, GregorianCalendar.JANUARY, 1).getTime();
    }

    public String createDescription() {
        return RandomStringUtils.randomAlphabetic(12);
    }

    public Employee createEmployee(Map<String, Object> context, Company hexacta, Person admin, Person person,
            JobTerm term) {
        Employee employee = new Employee();
        employee.setCompany(hexacta);
        employee.setCreatedBy(admin);
        employee.setCreatedDate(this.createCurrentDate());
        employee.setLastModifiedBy(admin);
        employee.setLastModifiedDate(this.createCurrentDate());
        employee.setDateStart(this.createDateStart());
        employee.setSalary(this.createSalary());
        employee.setPerson(person);
        // Creates the employee status
        EmployeeStatus status = new EmployeeStatus();
        status.setDateStart(this.createCurrentDate());
        status.setStatusType(term);
        employee.setStatus(Collections.singleton(status));

        CareerRole cr = new CareerRole();
        cr.setEffectiveDate(this.createCurrentDate());
        cr.setCondition(term);
        cr.setCareerRolePosition(25L);
        employee.getEmploymentConditionHistory().getCareerRoles().add(cr);
        AgreementCondition ac = new AgreementCondition();
        ac.setEffectiveDate(this.createCurrentDate());
        ac.setHoursPerDay(8d);
        employee.getEmploymentConditionHistory().getAgreementConditions().add(ac);

        return employee;
    }

    public Date createNextWeekDate() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.WEEK_OF_YEAR, 1);
        return calendar.getTime();
    }

    public Person createPerson(Map<String, Object> context, Domain hexactaDomain, Locale spanish, String name,
            String surname) {
        Person person = new Person();
        person.setDomain(hexactaDomain);
        person.setLocale(spanish);
        person.setFirstName(name);
        person.setLastName(surname);
        person.setCreatedBy(person);
        person.setCreatedDate(this.createCurrentDate());
        person.setLastModifiedBy(person);
        person.setLastModifiedDate(this.createCurrentDate());
        person.setDateOfBirth(this.createCurrentDate());
        person.setCuilOrCuit(Cuit.generar(8, 'm'));

        return person;
    }

    public String createPersonName() {
        return RandomStringUtils.randomAlphabetic(8);
    }

    public String createPhone() {
        return RandomStringUtils.randomNumeric(8);
    }

    public String createPostalCode() {
        return RandomStringUtils.randomNumeric(4);
    }

    public Date createPreviousMonthDate() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MONTH, -1);
        return calendar.getTime();
    }

    public Date createPreviousYearDate() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.YEAR, -1);
        return calendar.getTime();
    }

    public BigDecimal createSalary() {
        return new BigDecimal(10000);
    }

    public SessionFactory getSessionFactory() {
        return this.sessionFactory;
    }

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    protected final void flushSession() {
        new HibernateTemplate(this.getSessionFactory()).flush();
    }

    protected final Session getCurrentSession() {
        return this.getSessionFactory().getCurrentSession();
    }
    
    @SuppressWarnings("deprecation")
	public static Project createHRSProject() {
		Project internalProject = new Project();
		internalProject.setName("HRS");
		
		internalProject.addAssignment(createAssignment(new Date(2000,1,1), new Date(2009,12,20), AssignmentType.AddOnAvailable));
		internalProject.addAssignment(createAssignment(new Date(2000,1,1), new Date(2009,12,20), AssignmentType.AddOnNotAvailable));
		return internalProject;
	}

	@SuppressWarnings("deprecation")
	public static Project createIOLayerProject() {
		Project internalProject = new Project();
		internalProject.setName("IOLAYER");
		
		internalProject.addAssignment(createAssignment(new Date(2000,1,1), new Date(2009,12,20), AssignmentType.AddOnAvailable));
		internalProject.addAssignment(createAssignment(new Date(2000,1,1), new Date(2009,12,20), AssignmentType.AddOnNotAvailable));
		return internalProject;
	}

	@SuppressWarnings("deprecation")
	public static Project createWebuiProject() {
		Project internalProject = new Project();
		internalProject.setName("WEBUI");
		
		internalProject.addAssignment(createAssignment(new Date(2000,1,1), new Date(2009,12,20), AssignmentType.Assigned));
		internalProject.addAssignment(createAssignment(new Date(2000,1,1), new Date(2009,12,20), AssignmentType.AddOnAvailable));
		return internalProject;
	}

	@SuppressWarnings("deprecation")
	public static Project createCamProject() {
		Project internalProject = new Project();
		internalProject.setName("CAM");
		
		internalProject.addAssignment(createAssignment(new Date(2000,1,1), new Date(2003,11,20), AssignmentType.Assigned));
		internalProject.addAssignment(createAssignment(new Date(2005,2,1), new Date(2009,9,20), AssignmentType.Assigned));
		return internalProject;
	}
	
	@SuppressWarnings("deprecation")
	public static EmployeeAssignment createAssignment(Date startDate, Date endDate, AssignmentType type) {
		EmployeeAssignment assignment = new EmployeeAssignment();
		Calendar instance = Calendar.getInstance();
		
		instance.set(startDate.getYear(), startDate.getMonth(), startDate.getDate());
		assignment.setStartDate(instance);
		
		instance = Calendar.getInstance();
		instance.set(endDate.getYear(), endDate.getMonth(), endDate.getDate());
		assignment.setEndDate(instance);
		
		assignment.setAssignmentType(type);
		
		return assignment;
	}

	public static Client createClient() {
		Client client = new Client();
		client.setName("client test name");
		client.setLocation(createLocation());
		return client;
	}

	public static Location createLocation() {
		Location location = new Location();
		location.setId(new Long(1111111));
		location.setParent(null);
		location.setDomain(null);
		location.setDescription("test location description");
		location.setName("test location name");
		location.setTypeCode("code");
		location.setVoided(true);
		location.setApproved(true);
		return location;
	}

	public static Calendar createCalendarInstance(int year, int month, int day) {
		Calendar calendar = Calendar.getInstance();
		calendar.set(year, month, day);
		return calendar;
	}
}
